﻿#include<iostream>
#include<string>

//隐藏规则：在继承体系中基类和派生类都有独立的作用域，两种作用域不同
//派生类和基类中有同名成员，派生类成员将会屏蔽基类对同名成员的直接访问，这种情况叫隐藏
//没有构成隐藏时，继承体系下，基类对象的成员和派生类中继承下来的基类成员相互独立，不是同一个(地址不同)

//class Person
//{
//protected :
//	std::string _name = "小李子"; // 姓名
//	int _num = 111; // ⾝份证号
//public:
//	std::string* get_NameAddr()
//	{
//		return &_name;
//	}
//};
//class Student : public Person
//{
//	public :
//	void Print()
//	{
//		std::cout << " 姓名:" << _name << std::endl;
//		std::cout << " 身份证号:" << Person::_num << std::endl;
//		std::cout << " 学号:" << _num << std::endl;
//	}
//protected:
//	int _num = 999; // 学号
//};
//int main()
//{
//	Student s1;
//	Person s2;
//	s1.Print(); //这里基类和派生类的同名成员变量构成隐藏，注意成员函数函数名相同就构成隐藏
//	std::cout << s1.get_NameAddr() << std::endl; //获取基类对象的成员变量_name的地址
//	std::cout << s2.get_NameAddr() << std::endl;//获取派生类中基类对象成员变量_name的地址，两个地址不一样，说明相互独立
//	return 0;
//};

class Person {
public:
	virtual void BuyTicket() { std::cout << "买票-全价" << std::endl; }
};
class Student : public Person {
public:
	virtual void BuyTicket() { std::cout << "买票-打折" << std::endl; }
};
class Soldier : public Person {
public:
	virtual void BuyTicket() { std::cout << "买票-优先" << std::endl; }
};
void Func(Person* ptr)
{
	// 这⾥可以看到虽然都是Person指针Ptr在调⽤BuyTicket
	// 但是跟ptr没关系，⽽是由ptr指向的对象决定的。
	ptr->BuyTicket();
}

class Base {
public:
	virtual void func1() { std::cout << "Base::func1" << std::endl; }
	virtual void func2() { std::cout << "Base::func2" << std::endl; }
	void func5() { std::cout << "Base::func5" << std::endl; }
protected:
	int a = 1;
};
class Derive : public Base //派⽣类的虚函数表中包含基类的虚函数地址，派⽣类重写的虚函数地址，派⽣类⾃⼰的虚函数地址三个部分
{
	public :
	// 重写基类的func1
	virtual void func1() { std::cout << "Derive::func1" << std::endl; }
	virtual void func3() { std::cout << "Derive::func1" << std::endl; }
	void func4() { std::cout << "Derive::func4" << std::endl; }
protected:
	int b = 2;
};
int main()
{
	// 其次多态不仅仅发⽣在派⽣类对象之间，多个派⽣类继承基类，重写虚函数后
	// 多态也会发⽣在多个派⽣类之间。
	//Person ps;
	//注意:1、派生类由两部分构成，继承下来的基类和自己的成员
	//2、一般情况下，继承下来的基类中有虚函数表指针，自己就不会再生成
	//3、但这里继承下来的基类部分虚函数表指针和基类对象自己的虚函数表指针不是同一个
	//虚函数表存放在代码段（vs2022下）
	/*Student st;
	Soldier sr;
	Func(&ps);
	Func(&st);
	Func(&sr);*/
	Base b;
	Derive d;
	return 0;
}